package jsu.blogger.websocket;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import jakarta.websocket.*;
import jakarta.websocket.server.ServerEndpoint;
import jsu.blogger.handler.WebSocketHandler;
import jsu.blogger.pojo.LogRecord;
import jsu.blogger.pojo.WebSocketMessage;
import jsu.blogger.service.impl.LogServiceImpl;
import jsu.blogger.service.inter.LogService;
import jsu.blogger.util.MessageUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ConcurrentHashMap;
import java.util.Map;

@Controller
@ServerEndpoint(value = "/log/websocket/{uid}/{token}")
public class LogWebSocketServer {
    private static LogService logService = new LogServiceImpl();
    private static final Logger log = LoggerFactory.getLogger(LogWebSocketServer.class);
    private static Map<String, Session> onlineUserList = new ConcurrentHashMap<>();
    private static Map<String, Thread> userThreads = new ConcurrentHashMap<>(); // 用户线程映射表
    private static final String LOG_FILE_PATH = "src/main/resources/logs/app.log";

    @OnOpen
    public void onOpen(Session session) {
        String userId = session.getPathParameters().get("uid");
        try {
            if (!WebSocketHandler.isTokenValid(session)) {
                session.getBasicRemote().sendText("Token不合法！");
                session.close();
                return;
            }
            onlineUserList.put(userId, session);
        } catch (IOException e) {
            log.error("Error during opening WebSocket connection for userId: {}", userId, e);
        }
    }

    @OnMessage
    public void onMessage(String msg, Session session) {
        String userId = session.getPathParameters().get("uid");
        try {
            WebSocketMessage webSocketMessage = MessageUtil.parseJsonToWebSocketMessage(msg);

            if (webSocketMessage.getCode() == 3) {
                String latestLogTimeJson = webSocketMessage.getData().toString();
                String latestLogTime = extractLatestLogTimeFromJson(latestLogTimeJson);

                if (latestLogTime != null && !latestLogTime.isEmpty()) {
//                    log.info("开发者ID：" + userId + "请求更新" + latestLogTime + "后的日志记录");

                    // 中断旧线程
                    Thread oldThread = userThreads.get(userId);
                    if (oldThread != null && oldThread.isAlive()) {
                        oldThread.interrupt();
//                        log.info("开发者ID:{}刷新日志，中断开发者 {} 的旧日志线程", userId,userId);
                    }

                    // 创建新线程
                    Thread newThread = new Thread(() -> sendLogUpdates(userId, session, latestLogTime));
                    userThreads.put(userId, newThread); // 替换用户的线程
                    newThread.start();
                } else {
                    log.error("接收到无效的 latestLogTime: {}", latestLogTimeJson);
                }
            }
        } catch (Exception e) {
            log.error("Error processing message", e);
        }
    }

    private String extractLatestLogTimeFromJson(String json) {
        try {
            JSONObject jsonObject = JSON.parseObject(json);
            return jsonObject.getString("latestLogTime");
        } catch (Exception e) {
            log.error("解析 JSON 时出错: {}", json, e);
            return null;
        }
    }

    private void sendLogUpdates(String userId, Session session, String latestLogTime) {
        Path logFilePath = Paths.get(LOG_FILE_PATH);
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        long lastReadPosition = 0;

        try (BufferedReader reader = new BufferedReader(new FileReader(logFilePath.toFile()))) {
            Date latestLogDate = dateFormat.parse(latestLogTime);
            reader.skip(lastReadPosition);

            String line;
            while (session.isOpen() && !Thread.currentThread().isInterrupted()) {
                line = reader.readLine();
                if (line != null) {
                    if (!line.startsWith("---")) {
                        continue;
                    }
                    line = line.substring(3);
                    String logTimeStr = extractTimeFromLog(line);
                    if (logTimeStr != null) {
                        Date logTime = dateFormat.parse(logTimeStr);
                        if (logTime.after(latestLogDate)) {
                            processLogLine(line, session);
                        }
                    }
                    lastReadPosition += line.length() + System.lineSeparator().length();
                } else {
                    Thread.sleep(1000);
                }
            }
        } catch (IOException e) {
            log.error("读取日志文件或发送日志时出错: {}", e.getMessage());
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
//            log.info("用户 {} 的日志线程被中断", userId);
        } catch (Exception e) {
            log.error("日志更新线程异常: {}", e.getMessage());
        }
    }

    private void processLogLine(String logLine, Session session) {
        String[] parts = logLine.split("---");
        if (parts.length >= 4) {
            LogRecord logRecord = new LogRecord(parts[0], parts[1], parts[2], parts[3]);
            sendLogToClient(session, logRecord);
        }
    }

    private void sendLogToClient(Session session, LogRecord logRecord) {
        try {
            String json = JSON.toJSONString(logRecord);
            session.getBasicRemote().sendText(json);
        } catch (IOException e) {
            log.error("Error sending log to client", e);
        }
    }

    private String extractTimeFromLog(String logLine) {
        if (logLine.length() >= 19) {
            return logLine.substring(0, 19);
        }
        return null;
    }

    @OnClose
    public void onClose(Session session) {
        String userId = session.getPathParameters().get("uid");
        onlineUserList.remove(userId);

        // 中断并移除线程
        Thread userThread = userThreads.remove(userId);
        if (userThread != null && userThread.isAlive()) {
            userThread.interrupt();
//            log.info("用户 {} 下线，日志线程已关闭", userId);
        }

        try {
            session.close();
        } catch (IOException e) {
            log.error("Error closing session for userId: {}", userId, e);
        }
    }

    @OnError
    public void onError(Session session, Throwable error) {
        String userId = session.getPathParameters().get("uid");
        try {
            log.error("WebSocket error for userId: {}, sessionId: {}", userId, session.getId(), error);
            if (!session.isOpen()) {
                session.close();
            }
        } catch (Exception e) {
            log.error("Error closing session on error for userId: {}", userId, e);
        }
    }
}